package cn.core.cron.rest;

import cn.core.cron.eo.CronJob;
import cn.core.cron.qo.CronJobQO;
import cn.core.cron.service.CronJobService;
import cn.core.cron.vo.CronJobVO;
import cn.core.tool.exception.CoreException;
import cn.core.tool.rest.CoreController;
import cn.core.tool.util.CoreTool;
import cn.core.tool.util.Param;
import cn.core.tool.util.Res;
import com.google.gson.JsonSyntaxException;
import lombok.extern.log4j.Log4j2;
import org.quartz.JobPersistenceException;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * 定时任务 REST API
 */
@Log4j2
@RestController
@Scope("prototype")
@RequestMapping("cron/cronJob")
public class CronJobController extends CoreController {

  public static final String name = "定时任务";

  @Resource
  private CronJobService cronJobService;

  /**
   * 定时任务 >>> 保存
   * @param param 参数
   * @return 返回
   */
  @PostMapping(save)
  public Res<CronJob> save(@RequestBody Param<CronJob> param) throws Exception {
    Res<CronJob> res = new Res<>(name + succSave);
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.save(param.get()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 批量保存
   * @param param 参数
   * @return 返回
   */
  @PostMapping(saveBatch)
  public Res<CronJob> saveBatch(@RequestBody Param<CronJob> param) throws Exception {
    Res<CronJob> res = new Res<>(name + succSave);
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.saveBatch(param.getData()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 修改
   * @param param 参数
   * @return 返回
   */
  @PostMapping(update)
  public Res<CronJob> update(@RequestBody Param<CronJob> param) throws Exception {
    Res<CronJob> res = new Res<>(name + succUpdate);
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.update(param.get()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 批量修改
   * @param param 参数
   * @return 返回
   */
  @PostMapping(updateBatch)
  public Res<CronJob> updateBatch(@RequestBody Param<CronJob> param) throws Exception {
    Res<CronJob> res = new Res<>(name + succUpdate);
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.updateBatch(param.getData()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 删除
   * @param param 参数
   * @return 返回
   */
  @PostMapping(remove)
  public Res<CronJob> remove(@RequestBody Param<CronJob> param) throws Exception {
    Res<CronJob> res = new Res<>(name + succRemove);
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      cronJobService.remove(param.get());
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 批量删除
   * @param param 参数
   * @return 返回
   */
  @PostMapping(removeBatch)
  public Res<CronJob> removeBatch(@RequestBody Param<CronJob> param) throws Exception {
    Res<CronJob> res = new Res<>(name + succRemove);
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      cronJobService.removeBatch(param.getData());
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 数据量
   * @param param 参数
   * @return 返回
   */
  @PostMapping(count)
  public Res<CronJob> count(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJob> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        res.setCount(cronJobService.count(null));
      } else {
        res.setCount(cronJobService.count(param.get()));
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 主键查询
   * @param param 参数
   * @return 返回
   */
  @PostMapping(pk)
  public Res<CronJob> pk(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJob> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.pk(param.get()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 查询
   * @param param 参数
   * @return 返回
   */
  @PostMapping(query)
  public Res<CronJob> query(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJob> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        res.setData(cronJobService.query(null));
      } else {
        res.setData(cronJobService.query(param.get()));
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 分页
   * @param param 分页参数
   * @return 返回
   */
  @PostMapping(paging)
  public Res<CronJob> paging(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJob> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.paging(param));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 业务数据量
   * @param param 参数
   * @return 返回
   */
  @PostMapping(countVo)
  public Res<CronJobVO> countVo(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJobVO> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        res.setCount(cronJobService.countVo(null));
      } else {
        res.setCount(cronJobService.countVo(param.get()));
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 业务主键查询
   * @param param 参数
   * @return 返回
   */
  @PostMapping(pkVo)
  public Res<CronJobVO> pkVo(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJobVO> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.pkVo(param.get()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 业务查询
   * @param param 参数
   * @return 返回
   */
  @PostMapping(queryVo)
  public Res<CronJobVO> queryVo(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJobVO> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        res.setData(cronJobService.queryVo(null));
      } else {
        res.setData(cronJobService.queryVo(param.get()));
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 业务分页
   * @param param 分页参数
   * @return 返回
   */
  @PostMapping(pagingVo)
  public Res<CronJobVO> pagingVo(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJobVO> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.pagingVo(param));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 开始
   * @param param 参数
   * @return 返回
   */
  @PostMapping("start")
  public Res<CronJob> start(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJob> res = new Res<>("任务已开始！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.start(param.get()));
    } catch (ClassNotFoundException e) {
      res.setException("任务类名未找到！");
    } catch (IllegalArgumentException e) {
      res.setException("无效的任务类！");
    } catch (JsonSyntaxException e) {
      res.setException("任务参数Json格式不正确！");
    } catch (JobPersistenceException e) {
      res.setException("任务参数值必须为字符串！");
    } catch (RuntimeException e) {
      if (CoreTool.isNotNullStr(e.getMessage()) && e.getMessage().startsWith("CronExpression")) {
        return res.setException("无效的Cron表达式！");
      }
      throw e;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 停止
   * @param param 参数
   * @return 返回
   */
  @PostMapping("stop")
  public Res<CronJob> stop(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJob> res = new Res<>("任务已停止！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.stop(param.get()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 定时任务 >>> 立即执行一次
   * @param param 参数
   * @return 返回
   */
  @PostMapping("executeOnceImmediately")
  public Res<CronJob> executeOnceImmediately(@RequestBody Param<CronJobQO> param) throws Exception {
    Res<CronJob> res = new Res<>("任务已开始执行！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(cronJobService.executeOnceImmediately(param.get()));
    } catch (ClassNotFoundException e) {
      res.setException("任务类名未找到！");
    } catch (IllegalArgumentException e) {
      res.setException("无效的任务类！");
    } catch (JsonSyntaxException e) {
      res.setException("任务参数Json格式不正确！");
    } catch (JobPersistenceException e) {
      res.setException("任务参数值必须为字符串！");
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

}
